Blades HTML templates

Generic Nunjucks/Liquid templates for 11ty/Build Awesome, Jekyll, Shopify, etc.


Table of Contents

Install

Via npm
npm install @anyblades/blades
cd ./_includes # or where your includes dir is
ln -s ../node_modules/@anyblades/blades/_includes/blades

That's it! Now you can use HTML blades in your templates like this:

{% extends 'blades/*.njk' %}
{% include 'blades/*.njk' %}
{% include blades/*.liquid %}
{% render blades/* %}
Preconfigured

Base HTML

Usage in Nunjucks layout:

{% extends 'blades/html.njk' %}

{% block body %}...{% endblock %}

Living example: /anyblades/build-awesome-starter/blob/main/_includes/default.njk

How it works ```jinja2 #} {% if site.favicon_alt %} {% endif %} {{- title | string | striptags ~ ' | ' if title -}} {{- site.title -}}

{%- for href in site.styles %} {%- endfor %}

{%- for src in site.scripts %} {%- endfor %}

{{ content_for_header | safe }}

{% block body %} {% endblock %} ``` - `title | string` avoids error with `| striptags` when you pass a pure number.

Usage in Liquid layout:

{% capture body %}...{% endcapture %}

{% include blades/html.liquid %}

Living example: /anyblades/bladeswitch/blob/main/_includes/default.liquid

How it works ```liquid{% endcomment %} {% if site.favicon_alt %} {% endif %} {%- if title %}{{ title | strip_html | append: ' | ' }}{% endif -%} {{- site.title -}}

{%- for href in site.styles %} {%- endfor %}

{%- for src in site.scripts %} {%- endfor %}

{{ content_for_header }}

{{ body }} ```

Usage example for /docs/plugins/navigation/#bring-your-own-html-render-the-menu-items-manually:

{% assign links = collections.all | eleventyNavigation %}
{% render blades/links, links: links, current_url: page.url %}
How it works ```liquid{% endcomment %}
</details>
                

Sitemap

Usage example for /11ty/eleventy-plugin-rss:

---
permalink: /sitemap.xml
layout: false
eleventyExcludeFromCollections: true
---
{% include 'blades/sitemap.xml.njk' %}
How it works ```jinja2 #} {%- for page in collections.all %} {% if page.data.permalink != false %} {{ site.base }}{{ page.url }} {{ page.date | date }} {% endif %} {%- endfor %} ```

Appendix

Nunjucks tricks

Syntax highlighting in VS Code~editors

This is a modern fork of the original extension. It is specifically designed to solve the "11ty problem" where you mix Nunjucks and HTML.

Why it's better: It injects Nunjucks grammar directly into the standard HTML grammar. This means you get full Nunjucks highlighting and the editor still knows it's an HTML file, giving you better Emmet and CSS autocompletion.

No Config: It works out of the box without needing to manually map file associations in your settings.

Auto-formatting in VS Code~editors
  1. 🧩 Install /prettier/prettier-vscode (if not yet)

  2. Install a compatible Prettier plugin for your project, for example:

npm i -D prettier-plugin-jinja-template
  1. It might be tricky to find a well-maintained Nunjucks plugin, but jinja-template works just fine with .njk via .html override:
{
  "plugins": ["prettier-plugin-jinja-template"],
  "overrides": [
    {
      "files": ["*.njk", "*.html"],
      "options": {
        "parser": "jinja-template"
      }
    }
  ]
}

PRO TIP: If you already use /anyblades/blades, it’s even easier. You can simply:

ln -s ./node_modules/@anyblades/blades/.prettierrc.json
Sort array by attribute

Per official .njk documentation:

sort(arr, reverse, caseSens, attr)
Sort arr with JavaScript's arr.sort function. If reverse is true, result will be reversed. Sort is case-insensitive by default, but setting caseSens to true makes it case-sensitive. If attr is passed, will compare attr from each item.

But you can actually do this trick:

{% for item in array | sort(attribute='weight') %}
  ...
{% endfor %}

Liquid tricks

Syntax highlighting & auto-formatting in VS Code~editors
  1. 🧩 Install /prettier/prettier-vscode (if not yet)
  2. 🧩 Install /docs/storefronts/themes/tools/shopify-liquid-vscode
    (2-in-1 extension for highlighting & formatting)

This is a huge advantage for .liquid over .njk so far.

Create array
{% capture _new_array %}
1
2
3
{% endcapture %}
{% assign _new_array = _new_array | strip | split: '\n' %}
Beware: False Positives in .liquid

❌ Wrong:

{% if my_string %} This will always show if the string exists, even if empty. {% endif %}

✅ Right (Checking for content):

{% if my_string != blank %} This only shows if there is actual text. {% endif %}

✅ Right (Checking arrays/strings by size):

{% if my_array.size > 0 %} This ensures the list isn't empty. {% endif %}